﻿/*******************************************************************  
 * Copyright (C) vancl.com
 * All rights reserved. 
 * 
 * Created By: VANCLOA\hanxianlong
 * Create Date:2011/8/19 16:29:03
 * Last Modified By:VANCLOA\hanxianlong
 * Last Modified Date:2011/8/19 16:29:03
 * Description: PDM parser
 * ********************************************************************/
#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleCodeGenerator.Schema;
using System.Xml.Linq;
using SimpleCodeGenerator.Generators;
#endregion

namespace SimpleCodeGenerator.Parsers
{
	/// <summary>
	/// PDM parser
	/// </summary>
	public	class PDMParser:IParser
	{
		class PDMNameSpaces
		{
			public static XNamespace a = "attribute";
			public static XNamespace c = "collection";
			public static XNamespace o = "object";
		}

		public List<TableSchema> ParseFromFile(string pdmPath)
		{
			XDocument document = null;
			document = XDocument.Load(pdmPath);

			var root = document.Root;
			var tablesElement = root.Element(PDMNameSpaces.o + "RootObject").Element(PDMNameSpaces.c + "Children")
				.Element(PDMNameSpaces.o + "Model").Element(PDMNameSpaces.c + "Tables").Elements(PDMNameSpaces.o + "Table");

			var tables =new List<TableSchema>();
			foreach (var tableElement in tablesElement)
			{
				tables.Add(parseTable(tableElement));
			}

			return tables;
		}

		private TableSchema parseTable(XElement tableElement)
		{
			string name = tableElement.Element(PDMNameSpaces.a + "Name").Value;
			string code = tableElement.Element(PDMNameSpaces.a + "Code").Value;

            XElement eleComment = tableElement.Element(PDMNameSpaces.a + "Comment");
            string comment = eleComment==null?"":eleComment.Value;
			IEnumerable<string> primaryKeyIds = tableElement.Element(PDMNameSpaces.c + "PrimaryKey")
								.Elements(PDMNameSpaces.o + "Key").Select(m => m.Attribute("Ref").Value);

			List<string> keysIdList = new List<string>();

			IEnumerable<XElement> keysElement = tableElement.Element(PDMNameSpaces.c + "Keys")
								.Elements(PDMNameSpaces.o + "Key");
			keysElement.ToList().ForEach(ele => ele.Element(PDMNameSpaces.c + "Key.Columns")
												.Elements(PDMNameSpaces.o + "Column")
												.ToList()
												.ForEach(c => keysIdList.Add(c.Attribute("Ref").Value))
												);

			TableSchema tempTable = new TableSchema();
			tempTable.Name = name;
			tempTable.Code = code;
			tempTable.Comment = comment;

			var columsElement = tableElement.Element(PDMNameSpaces.c + "Columns");
			List<ColumnSchema> columns = parseColumns(columsElement, keysIdList);
			tempTable.Columns = columns;
			tempTable.PrimaryKeyColumns = columns.Where(c => c.IsPrimaryKey).ToList();
			return tempTable;
		}

		private List<ColumnSchema> parseColumns(XElement columsElement, List<string> keysIdList)
		{
			var columnElementCollection = columsElement.Elements(PDMNameSpaces.o + "Column");
			var columnList = new List<ColumnSchema>();

			foreach (var columnElement in columnElementCollection)
			{
				var mandatoryElement = columnElement.Element(PDMNameSpaces.a + "Mandatory");
				var identityElement = columnElement.Element(PDMNameSpaces.a + "Identity");
				var lengthElement = columnElement.Element(PDMNameSpaces.a + "Length");
				string name = columnElement.Element(PDMNameSpaces.a + "Name").Value;
				string code = columnElement.Element(PDMNameSpaces.a + "Code").Value;

                XElement eleComment = columnElement.Element(PDMNameSpaces.a + "Comment");
				string comment = eleComment ==null?"":eleComment.Value;
				string type = columnElement.Element(PDMNameSpaces.a + "DataType").Value;
				string id = columnElement.Attribute("Id").Value;
				bool isNullable = true;
				bool isPrimaryKey = keysIdList.Exists(pk => string.Compare(pk, id) == 0);
				bool isIdentity = false;

				if (identityElement != null && string.Compare(identityElement.Value, "1") == 0)
				{
					isIdentity = true;
					comment += ",自增";
				}

				if (mandatoryElement != null && string.Compare(mandatoryElement.Value, "1") == 0)
				{
					isNullable = false;
				}

				if (isPrimaryKey)
				{
					comment += ",主键";
				}

				if (lengthElement != null)
				{
					comment += ",最大长度:" + lengthElement.Value;
				}

				type = TypeConverter.ConvertFromPDMTypeToCSharpType(type);

				var column = new ColumnSchema()
				{
					Name = name,
					Code = code,
					DataType = type,
					Comment = comment,
					IsNullable = isNullable,
					IsPrimaryKey = isPrimaryKey,
					IsIdentity = isIdentity
				};

				columnList.Add(column);
			}

			return columnList;
		}
	}
}
